home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / Source.bin / ProgressBar.java < prev    next >
Text File  |  1998-10-20  |  35KB  |  1,139 lines

  1. package symantec.itools.awt.util;
  2.  
  3. import java.awt.Canvas;
  4. import java.awt.Dimension;
  5. import java.awt.Color;
  6. import java.awt.Font;
  7. import java.awt.FontMetrics;
  8. import java.awt.Graphics;
  9. import java.awt.Rectangle;
  10. import java.awt.Image;
  11. import java.awt.MediaTracker;
  12. import java.beans.PropertyVetoException;
  13. import java.beans.PropertyChangeListener;
  14. import java.beans.VetoableChangeListener;
  15. import java.beans.PropertyChangeEvent;
  16. import symantec.itools.awt.AlignStyle;
  17. import symantec.itools.awt.BevelStyle;
  18. import symantec.itools.awt.util.ColorUtils;
  19. import symantec.itools.util.GeneralUtils;
  20.  
  21. //    06/02/97    TG    Updated to support Java 1.1
  22. //                    Made properties bound & constrained
  23. //    06/09/97    LAB    Polished for 1.1.  Added binding and constraining to setValue(...)
  24. //    07/18/97    LAB    Changed incorrect calls to invalidate() to repaint(). Deprecated preferredSize and
  25. //                    minimumSize in favor of getPreferredSize and getMinimumSize
  26. //    08/26/97    LAB    Changed the default bevel style to line (Addresses Mac Bug #7380).  Changed the
  27. //                    property name strings in bound and constrained event messages to match the Bean
  28. //                    Spec naming conventions. Deprecated ProgressBarTextColor property and made the
  29. //                    text use the Foreground color (Addresses Mac Bug #7498).  Made the bar use an
  30. //                    offscreen buffer to draw into to eliminate flicker when in box mode. Deprecated
  31. //                    BorderedColor property in favor of BorderColor.  Updated the way the component
  32. //                    draws itself (Addresses Mac Bug #7492).
  33. //    08/27/97    LAB    Removed an unnecessary fillRect in updateBufferImage.
  34. //    10/23/97    LAB    Constrained the BoxWidth and GapWidth properties (Addresses Mac Bug #9702).
  35.  
  36. /**
  37.  * ProgressBar component.
  38.  * Creates a bar that displays a percentage.
  39.  * Commonly used to indicate the percentage completed of a
  40.  * lengthy task.
  41.  * @version 1.1, August 26, 1997
  42.  * @author Symantec
  43.  */
  44. public class ProgressBar extends Canvas implements BevelStyle, AlignStyle
  45.  {
  46.    /**
  47.      * Border Indent constant INDENT_ZERO.
  48.      */
  49.     public static final int INDENT_ZERO = 0;
  50.  
  51.     /**
  52.      * Border Indent constant INDENT_ONE.
  53.      */
  54.     public static final int INDENT_ONE = 1;
  55.  
  56.     /**
  57.      * Border Indent constant INDENT_TWO.
  58.      */
  59.     public static final int INDENT_TWO = 2;
  60.  
  61.     /**
  62.      * Constructs a progress bar with a centered progress %, line border and zero indentation.
  63.      */
  64.     public ProgressBar()
  65.     {
  66.         this(ALIGN_CENTERED, BEVEL_LINE, INDENT_ZERO);
  67.     }
  68.  
  69.     /**
  70.      * Constructs a progress bar with the style and indentation variables specified.
  71.      * The default parameters are the border color and progress % color as black, the progress bar color
  72.      * as blue.
  73.      * @param align progress bar alignment style
  74.      * @param bevel progress bar bevel style
  75.      * @param indent border indent INDENT_ZERO, INDENT_ONE, or INDENT_TWO
  76.      */
  77.     public ProgressBar(int align, int bevel, int indent)
  78.     {
  79.         // set default values
  80.         borderColor        = Color.black;
  81.         progressColor    = Color.blue;
  82.         bShowProgress    = true;
  83.         bDrawBoxes        = false;
  84.         progress        = 0;
  85.         boxWidth        = 8;
  86.         gapWidth        = 2;
  87.  
  88.         cachedBackground = getBackground();
  89.  
  90.         // process arguments
  91.  
  92.         try
  93.         {
  94.             setBorderIndent(indent, false);
  95.             setBevelStyle(bevel);
  96.             setAlignStyle(align);
  97.         }
  98.         catch(PropertyVetoException veto) {};
  99.  
  100.         //Hook up listeners here so bad values set before addNotify is called get range checked.
  101.         if (boxVeto == null)
  102.         {
  103.             boxVeto = new BoxVeto();
  104.             addBoxWidthListener(boxVeto);
  105.         }
  106.         if (gapVeto == null)
  107.         {
  108.             gapVeto = new GapVeto();
  109.             addGapWidthListener(gapVeto);
  110.         }
  111.     }
  112.  
  113.     /**
  114.      * Set the color that the progress bar will be drawn in.
  115.      * @param color the color that the progress bar will be drawn in.
  116.      * @see #getProgressBarColor
  117.      * @exception PropertyVetoException
  118.      * if the specified property value is unacceptable
  119.      */
  120.     public void setProgressBarColor(Color c) throws PropertyVetoException
  121.     {
  122.         if (!symantec.itools.util.GeneralUtils.objectsEqual(progressColor,c))
  123.         {
  124.             Color oldValue = progressColor;
  125.  
  126.             vetos.fireVetoableChange("progressBarColor", oldValue, c);
  127.  
  128.             progressColor = c;
  129.             repaint();
  130.  
  131.                changes.firePropertyChange("progressBarColor", oldValue, c);
  132.         }
  133.     }
  134.  
  135.     /**
  136.      * Get the color that the progress bar will be drawing in.  The default color is blue.
  137.      * @return Color that the Progress Bar will be drawn in.
  138.      * @see #setProgressBarColor
  139.      */
  140.     public Color getProgressBarColor()
  141.     {
  142.         return progressColor;
  143.     }
  144.  
  145.     /**
  146.      * @deprecated
  147.      * @see java.awt.Component#setForeground
  148.      * @exception PropertyVetoException
  149.      * if the specified property value is unacceptable
  150.      */
  151.     public void setProgressBarTextColor(Color c) throws PropertyVetoException
  152.     {
  153.         setForeground(c);
  154.     }
  155.  
  156.     /**
  157.      * @deprecated
  158.      * @see java.awt.Component#getForeground()
  159.      */
  160.     public Color getProgressBarTextColor()
  161.     {
  162.         return getForeground();
  163.     }
  164.  
  165.     /**
  166.      * Set the boolean that controls the drawing of the progress bar as a series of boxes.
  167.      * @param b indicating if the bar should be composed of multiple boxes.
  168.      * @exception PropertyVetoException
  169.      * if the specified property value is unacceptable
  170.      * @see #getDrawBoxes
  171.      */
  172.     public void setDrawBoxes(boolean b) throws PropertyVetoException
  173.     {
  174.         if (bDrawBoxes != b)
  175.         {
  176.             Boolean oldDrawBoxesBoolean = new Boolean(bDrawBoxes);
  177.             Boolean newDrawBoxesBoolean = new Boolean(b);
  178.  
  179.             vetos.fireVetoableChange("drawBoxes", oldDrawBoxesBoolean, newDrawBoxesBoolean);
  180.  
  181.             bDrawBoxes = b;
  182.             repaint();
  183.  
  184.             changes.firePropertyChange("drawBoxes", oldDrawBoxesBoolean, newDrawBoxesBoolean);
  185.         }
  186.     }
  187.  
  188.     /**
  189.      * Get the boolean that controls the drawing of the progress bar as a series of boxes.
  190.      * The default value is false.
  191.      * @return boolean indicating if the bar should be composed of multiple boxes.
  192.      * @see #setDrawBoxes
  193.      */
  194.      public boolean isDrawBoxes()
  195.      {
  196.          return bDrawBoxes;
  197.      }
  198.  
  199.     /**
  200.      * @deprecated
  201.      * @see #isDrawBoxes()
  202.      */
  203.     public boolean getDrawBoxes()
  204.     {
  205.         return isDrawBoxes();
  206.     }
  207.  
  208.     /**
  209.      * Set the width of the boxes drawn for the progress bar.
  210.      * @param i the pixel width of the boxes in the progress bar.
  211.      * @exception PropertyVetoException
  212.      * if the specified property value is unacceptable
  213.      * @see #getBoxWidth
  214.      */
  215.     public void setBoxWidth(int i)  throws PropertyVetoException
  216.     {
  217.         Integer newValue = new Integer(i);
  218.         Integer oldValue = new Integer(boxWidth);
  219.  
  220.         vetos.fireVetoableChange("boxWidth", oldValue, newValue);
  221.  
  222.         boxWidth = i;
  223.         repaint();
  224.  
  225.         changes.firePropertyChange("boxWidth", oldValue, newValue);
  226.     }
  227.  
  228.     /**
  229.      * Get the width of the boxes drawn for the progress bar.  The default value is 8 pixels.
  230.      * @return int the pixel width of the boxes in the progress bar.
  231.      * @see #setBoxWidth
  232.      */
  233.     public int getBoxWidth()
  234.     {
  235.         return boxWidth;
  236.     }
  237.  
  238.     /**
  239.      * Set the gap width between boxes drawn for the progress bar.
  240.      * @param i the pixel width of the boxes in the progress bar.
  241.      * @exception PropertyVetoException
  242.      * if the specified property value is unacceptable
  243.      * @see #getBoxWidth
  244.      * @see #getGapWidth
  245.      */
  246.     public void setGapWidth(int i) throws PropertyVetoException
  247.  
  248.     {
  249.         Integer newValue = new Integer(i);
  250.         Integer oldValue = new Integer(gapWidth);
  251.  
  252.         vetos.fireVetoableChange("gapWidth", oldValue, newValue);
  253.  
  254.         gapWidth = i;
  255.         repaint();
  256.  
  257.         changes.firePropertyChange("gapWidth", oldValue, newValue);
  258.     }
  259.  
  260.     /**
  261.      * Get the gap width of the boxes drawn for the progress bar.  The default value is 2 pixels.
  262.      * @return i the pixel width of the gap between boxes in the progress bar.
  263.      * @see #setBoxWidth
  264.      * @see #setGapWidth
  265.      */
  266.     public int getGapWidth()
  267.     {
  268.         return gapWidth;
  269.     }
  270.  
  271.      /**
  272.      * @deprecated
  273.      * @see #isShowProgress
  274.      */
  275.     public boolean getShowProgress()
  276.     {
  277.         return isShowProgress();
  278.     }
  279.  
  280.     /**
  281.      * Set the boolean that controls the display of the progress number as an percentage.
  282.      * @param b indicating if the progress percentage should be displayed.
  283.      * @exception PropertyVetoException
  284.      * if the specified property value is unacceptable
  285.      * @see #getShowProgress
  286.      */
  287.     public void setShowProgress(boolean b) throws PropertyVetoException
  288.     {
  289.         if ( bShowProgress != b)
  290.         {
  291.             Boolean oldValue = new Boolean(bShowProgress);
  292.             Boolean newValue = new Boolean(b);
  293.  
  294.             vetos.fireVetoableChange("showProgress", oldValue, newValue);
  295.  
  296.             bShowProgress = b;
  297.             repaint();
  298.  
  299.             changes.firePropertyChange("showProgress", oldValue, newValue);
  300.         }
  301.  
  302.     }
  303.  
  304.     /**
  305.      * Get the boolean that controls the display of the progress number as a percentage.
  306.      * The default value is true
  307.      * @return boolean indicating if the number should be displayed.
  308.      * @see #setShowProgress
  309.      */
  310.      public boolean isShowProgress()
  311.      {
  312.          return bShowProgress;
  313.      }
  314.  
  315.     /**
  316.      * Set the style of the progress bar's alignment.
  317.      * @param style numeric value indicating the progress bar's alignment
  318.      * @exception PropertyVetoException
  319.      * if the specified property value is unacceptable
  320.      * @see #getAlignStyle
  321.      */
  322.     public void setAlignStyle(int style) throws PropertyVetoException
  323.     {
  324.         Integer newValue = new Integer (style);
  325.         Integer oldValue = new Integer (align);
  326.  
  327.         vetos.fireVetoableChange("alignStyle", oldValue, newValue);
  328.  
  329.         align = style;
  330.         repaint();
  331.  
  332.         changes.firePropertyChange("alignStyle", oldValue, newValue);
  333.     }
  334.  
  335.     /**
  336.      * Get the current style of the progress bar's alignment
  337.      * @return int the style numeric value indicating progress bar's alignment
  338.      * @see #setAlignStyle
  339.      */
  340.     public int getAlignStyle()
  341.     {
  342.         return align;
  343.     }
  344.  
  345.     /**
  346.      * Set the style of the progress bar's border.
  347.      * @param style numeric value indicating the progress bar's style
  348.      * @exception PropertyVetoException
  349.      * if the specified property value is unacceptable
  350.      * @see #getBevelStyle
  351.      */
  352.     public void setBevelStyle(int style)  throws PropertyVetoException
  353.     {
  354.         if(type != style)
  355.         {
  356.             Integer oldValue = new Integer (type);
  357.             Integer newValue = new Integer (style);
  358.  
  359.             vetos.fireVetoableChange("bevelStyle", oldValue, newValue);
  360.  
  361.             type = style;
  362.  
  363.             repaint();
  364.  
  365.             changes.firePropertyChange("bevelStyle", oldValue, newValue);
  366.         }
  367.     }
  368.  
  369.     /**
  370.      * Get the current style of the progress bar's border
  371.      * @return int the style numeric value indicating progress bar's border, such as BEVEL_LOWERED
  372.      * @see #setBevelStyle
  373.      */
  374.     public int getBevelStyle()
  375.     {
  376.         return type;
  377.     }
  378.  
  379.     /**
  380.      * Set the border indent amount.
  381.      * @param indent INDENT_ZERO, INDENT_ONE or INDENT_TWO
  382.      * @exception PropertyVetoException
  383.      * if the specified property value is unacceptable
  384.      * @see #getBorderIndent
  385.      * @see #setBorderIndent(int, boolean)
  386.      */
  387.     public void setBorderIndent(int indent) throws PropertyVetoException
  388.     {
  389.         setBorderIndent(indent, true);
  390.     }
  391.  
  392.     /**
  393.      * Get the border indent amount.  The default value is INDENT_ZERO.
  394.      * @return int INDENT_ZERO, INDENT_ONE or INDENT_TWO
  395.      * @see #setBorderIndent
  396.      */
  397.     public int getBorderIndent()
  398.     {
  399.         return indent;
  400.     }
  401.  
  402.     /**
  403.      * Set the color for the border of BEVEL_LINE style ProgressBar.  This will not be used for other styles.
  404.      * @param color color that the border will be drawn in.
  405.      * @exception PropertyVetoException
  406.      * if the specified property value is unacceptable
  407.      * @see #getBorderColor
  408.      */
  409.     public void setBorderColor(Color color) throws PropertyVetoException
  410.     {
  411.         if (!symantec.itools.util.GeneralUtils.objectsEqual(borderColor, color))
  412.         {
  413.             Color oldValue = getBorderColor();
  414.  
  415.             vetos.fireVetoableChange("borderColor", oldValue, color);
  416.  
  417.               borderColor = color;
  418.             repaint();
  419.  
  420.             changes.firePropertyChange("borderColor", oldValue, color);
  421.         }
  422.     }
  423.  
  424.     /**
  425.      * Get the color for the border of BEVEL_LINE style ProgressBar.  This will not be used for other styles.
  426.      * @return Color that the border will be drawn in.
  427.      * @see #setBorderColor
  428.      */
  429.     public Color getBorderColor()
  430.     {
  431.         return borderColor;
  432.     }
  433.  
  434.     /**
  435.      * @deprecated
  436.      * @see #setBorderColor
  437.      * @exception PropertyVetoException
  438.      * if the specified property value is unacceptable
  439.      */
  440.     public void setBorderedColor(Color color) throws PropertyVetoException
  441.     {
  442.         setBorderColor(color);
  443.     }
  444.  
  445.     /**
  446.      * @deprecated
  447.      * @see #getBorderColor
  448.      */
  449.     public Color getBorderedColor()
  450.     {
  451.         return getBorderColor();
  452.     }
  453.  
  454.     /**
  455.      * Set the percentage complete for the process being tracked.
  456.      * @param p percentage complete as an integer
  457.      * @exception PropertyVetoException
  458.      * if the specified property value is unacceptable
  459.      */
  460.     public void setProgressPercent(int p) throws PropertyVetoException
  461.     {
  462.         if (p < 0) p = 0;
  463.         if (p > 100) p = 100;
  464.         if(progress != p)
  465.         {
  466.             Integer oldValue = new Integer(progress);
  467.             Integer newValue = new Integer(p);
  468.             vetos.fireVetoableChange("progressPercent", oldValue, newValue);
  469.             progress = p;
  470.             repaint();
  471.             changes.firePropertyChange("progressPercent", oldValue, newValue);
  472.         }
  473.     }
  474.  
  475.     /**
  476.      * @deprecated
  477.      * @see #setProgressPercent
  478.      * @exception PropertyVetoException
  479.      * if the specified property value is unacceptable
  480.      */
  481.     public void updateProgress(int p) throws PropertyVetoException
  482.     {
  483.         setProgressPercent(p);
  484.     }
  485.  
  486.     /**
  487.      * Get the current percentage complete.
  488.      * @return int - current percentage complete
  489.      * @see #setProgressPercent
  490.      */
  491.     public int getProgressPercent()
  492.     {
  493.         return progress;
  494.     }
  495.  
  496.     /**
  497.      * Set the current percentage complete.
  498.      * @param p percentage complete
  499.      * @exception PropertyVetoException
  500.      * if the specified property value is unacceptable
  501.      * @see #getValue
  502.      */
  503.     public void setValue(int p) throws PropertyVetoException
  504.     {
  505.         // !!! LAB !!! In the future this should be different from ProgressPercent
  506.         // in that, the user could specify a start and end value, and the percent
  507.         // would be calculated for them.  Thus, this would set some intermediate
  508.         // value, not the percentage.
  509.         setProgressPercent(p);
  510.     }
  511.  
  512.     /**
  513.      * Get the current percentage complete.
  514.      * @return int - current percentage complete
  515.      * @see #setValue
  516.      */
  517.     public int getValue()
  518.     {
  519.         // !!! LAB !!! In the future this should be different from ProgressPercent
  520.         // in that, the user could specify a start and end value, and the percent
  521.         // would be calculated for them.  Thus, this would get some intermediate
  522.         // value, not the percentage.
  523.         return progress;
  524.     }
  525.  
  526.     /**
  527.      * Handles redrawing of this component on the screen.
  528.      * This is a standard Java AWT method which gets called by the Java
  529.      * AWT (repaint()) to handle repainting this component on the screen.
  530.      * The graphics context clipping region is set to the bounding rectangle
  531.      * of this component and its <0,0> coordinate is this component's
  532.      * top-left corner.
  533.      * Typically this method paints the background color to clear the
  534.      * component's drawing space, sets graphics context to be the foreground
  535.      * color, and then calls paint() to draw the component.
  536.      *
  537.      * It is overridden here to reduce flicker by eliminating the uneeded
  538.      * clearing of the background.
  539.      *
  540.      * @param g the graphics context
  541.      * @see java.awt.Component#repaint
  542.      * @see #paint
  543.      */
  544.     public void update(Graphics g)
  545.     {
  546.         paint(g);
  547.     }
  548.  
  549.  
  550.     /**
  551.      * Paints this component using the given graphics context.
  552.      * This is a standard Java AWT method which typically gets called
  553.      * by the AWT to handle painting this component. It paints this component
  554.      * using the given graphics context. The graphics context clipping region
  555.      * is set to the bounding rectangle of this component and its <0,0>
  556.      * coordinate is this component's top-left corner.
  557.      *
  558.      * @param g the graphics context used for painting
  559.      * @see java.awt.Component#repaint
  560.      * @see #update
  561.      */
  562.     public void paint(Graphics g)
  563.     {
  564.         Color curBackground = getBackground();
  565.         if (!symantec.itools.util.GeneralUtils.objectsEqual(curBackground, cachedBackground))
  566.         {
  567.             cachedBackground = curBackground;
  568.             calculateHilightColors(curBackground);
  569.         }
  570.         updateBufferImage();
  571.         g.drawImage(bufferImage, 0, 0, this);
  572.     }
  573.  
  574.     /**
  575.      * Returns the recommended dimensions to properly display this component.
  576.      * This is a standard Java AWT method which gets called to determine
  577.      * the recommended size of this component.
  578.      *
  579.      * @see #getMinimumSize
  580.      */
  581.     public Dimension getPreferredSize()
  582.     {
  583.         Dimension s = getSize();
  584.         Dimension m = getMinimumSize();
  585.  
  586.         return new Dimension(Math.max(s.width, m.width), Math.max(s.height, m.height));
  587.     }
  588.  
  589.     /**
  590.      * @deprecated
  591.      * @see #getPreferredSize
  592.      */
  593.     public Dimension preferredSize()
  594.     {
  595.         return getPreferredSize();
  596.     }
  597.  
  598.     /**
  599.      * Returns the minimum dimensions to properly display this component.
  600.      * This is a standard Java AWT method which gets called to determine
  601.      * the minimum size of this component.
  602.      *
  603.      * @see #getPreferredSize
  604.      */
  605.     public Dimension getMinimumSize()
  606.     {
  607.         Font f = null;
  608.         FontMetrics fm = null;
  609.  
  610.         f = getFont();
  611.         if(f != null)
  612.             fm = getFontMetrics(f);
  613.  
  614.         if(fm != null) {
  615.             return new Dimension(50, fm.getHeight() + 4);
  616.         }
  617.         else {
  618.             return new Dimension(50, 20);
  619.         }
  620.     }
  621.  
  622.     /**
  623.      * @deprecated
  624.      * @see #getMinimumSize
  625.      */
  626.     public Dimension minimumSize()
  627.     {
  628.         return getMinimumSize();
  629.     }
  630.  
  631.     /**
  632.      * Tells this component that it has been added to a container.
  633.      * This is a standard Java AWT method which gets called by the AWT when
  634.      * this component is added to a container. Typically, it is used to
  635.      * create this component's peer.
  636.      *
  637.      * It has been overridden here to hook-up event listeners.
  638.      *
  639.      * @see #removeNotify
  640.      */
  641.     public synchronized void addNotify()
  642.     {
  643.         //Hook up listeners
  644.         if (boxVeto == null)
  645.         {
  646.             boxVeto = new BoxVeto();
  647.             addBoxWidthListener(boxVeto);
  648.         }
  649.         if (gapVeto == null)
  650.         {
  651.             gapVeto = new GapVeto();
  652.             addGapWidthListener(gapVeto);
  653.         }
  654.         //Add after the listeners are hooked up
  655.         super.addNotify();
  656.     }
  657.  
  658.     /**
  659.      * Tells this component that it is being removed from a container.
  660.      * This is a standard Java AWT method which gets called by the AWT when
  661.      * this component is removed from a container. Typically, it is used to
  662.      * destroy the peers of this component and all its subcomponents.
  663.      *
  664.      * It has been overridden here to unhook event listeners.
  665.      *
  666.      * @see #addNotify
  667.      */
  668.     public synchronized void removeNotify()
  669.     {
  670.         //Unhook listeners
  671.         if (boxVeto != null)
  672.         {
  673.             removeBoxWidthListener(boxVeto);
  674.             boxVeto = null;
  675.         }
  676.         if (gapVeto != null)
  677.         {
  678.             removeGapWidthListener(gapVeto);
  679.             gapVeto = null;
  680.         }
  681.  
  682.         super.removeNotify();
  683.     }
  684.  
  685.     /**
  686.      * Adds a listener for all event changes.
  687.      * @param PropertyChangeListener listener the listener to add.
  688.      * @see #removePropertyChangeListener
  689.      */
  690.     public synchronized void addPropertyChangeListener(PropertyChangeListener listener)
  691.     {
  692.         //super.addPropertyChangeListener(listener);
  693.         changes.addPropertyChangeListener(listener);
  694.     }
  695.  
  696.     /**
  697.      * Removes a listener for all event changes.
  698.      * @param PropertyChangeListener listener the listener to remove.
  699.      * @see #addPropertyChangeListener
  700.      */
  701.     public synchronized void removePropertyChangeListener(PropertyChangeListener listener)
  702.     {
  703.         //super.removePropertyChangeListener(listener);
  704.         changes.removePropertyChangeListener(listener);
  705.     }
  706.  
  707.     /**
  708.      * Adds a vetoable listener for all event changes.
  709.      * @param VetoableChangeListener listener the listener to add.
  710.      * @see #removeVetoableChangeListener
  711.      */
  712.     public synchronized void addVetoableChangeListener(VetoableChangeListener listener)
  713.     {
  714.          //super.addVetoableChangeListener(listener);
  715.         vetos.addVetoableChangeListener(listener);
  716.     }
  717.  
  718.     /**
  719.      * Removes a vetoable listener for all event changes.
  720.      * @param VetoableChangeListener listener the listener to remove.
  721.      * @see #addVetoableChangeListener
  722.      */
  723.     public synchronized void removeVetoableChangeListener(VetoableChangeListener listener)
  724.     {
  725.         //super.removeVetoableChangeListener(listener);
  726.         vetos.removeVetoableChangeListener(listener);
  727.     }
  728.  
  729.     /**
  730.      * Adds a listener for the GapWidth property changes.
  731.      * @param listener the listener to add.
  732.      * @see #removeGapWidthListener(java.beans.PropertyChangeListener)
  733.      */
  734.     public synchronized void addGapWidthListener(PropertyChangeListener listener)
  735.     {
  736.         changes.addPropertyChangeListener("gapWidth", listener);
  737.     }
  738.  
  739.     /**
  740.      * Removes a listener for the GapWidth property changes.
  741.      * @param listener the listener to remove.
  742.      * @see #addGapWidthListener(java.beans.PropertyChangeListener)
  743.      */
  744.     public synchronized void removeGapWidthListener(PropertyChangeListener listener)
  745.     {
  746.         changes.removePropertyChangeListener("gapWidth", listener);
  747.     }
  748.  
  749.     /**
  750.      * Adds a vetoable listener for the GapWidth property changes.
  751.      * @param listener the listener to add.
  752.      * @see #removeGapWidthListener(java.beans.VetoableChangeListener)
  753.      */
  754.     public synchronized void addGapWidthListener(VetoableChangeListener listener)
  755.     {
  756.         vetos.addVetoableChangeListener("gapWidth", listener);
  757.     }
  758.  
  759.     /**
  760.      * Removes a vetoable listener for the GapWidth property changes.
  761.      * @param listener the listener to remove.
  762.      * @see #addGapWidthListener(java.beans.VetoableChangeListener)
  763.      */
  764.     public synchronized void removeGapWidthListener(VetoableChangeListener listener)
  765.     {
  766.         vetos.removeVetoableChangeListener("gapWidth", listener);
  767.     }
  768.  
  769.     /**
  770.      * Adds a listener for the BoxWidth property changes.
  771.      * @param listener the listener to add.
  772.      * @see #removeBoxWidthListener(java.beans.PropertyChangeListener)
  773.      */
  774.     public synchronized void addBoxWidthListener(PropertyChangeListener listener)
  775.     {
  776.         changes.addPropertyChangeListener("boxWidth", listener);
  777.     }
  778.  
  779.     /**
  780.      * Removes a listener for the BoxWidth property changes.
  781.      * @param listener the listener to remove.
  782.      * @see #addBoxWidthListener(java.beans.PropertyChangeListener)
  783.      */
  784.     public synchronized void removeBoxWidthListener(PropertyChangeListener listener)
  785.     {
  786.         changes.removePropertyChangeListener("boxWidth", listener);
  787.     }
  788.  
  789.     /**
  790.      * Adds a vetoable listener for the BoxWidth property changes.
  791.      * @param listener the listener to add.
  792.      * @see #removeBoxWidthListener(java.beans.VetoableChangeListener)
  793.      */
  794.     public synchronized void addBoxWidthListener(VetoableChangeListener listener)
  795.     {
  796.         vetos.addVetoableChangeListener("boxWidth", listener);
  797.     }
  798.  
  799.     /**
  800.      * Removes a vetoable listener for the BoxWidth property changes.
  801.      * @param listener the listener to remove.
  802.      * @see #addBoxWidthListener(java.beans.VetoableChangeListener)
  803.      */
  804.     public synchronized void removeBoxWidthListener(VetoableChangeListener listener)
  805.     {
  806.         vetos.removeVetoableChangeListener("boxWidth", listener);
  807.     }
  808.  
  809.     /**
  810.      * This is the PropertyChangeEvent handling inner class for the constrained BoxWidth property.
  811.      * Handles vetoing BevelHeights that are not valid.
  812.      */
  813.     class BoxVeto implements java.beans.VetoableChangeListener, java.io.Serializable
  814.     {
  815.         /**
  816.          * This method gets called when an attempt to change the constrained BoxWidth property is made.
  817.          * Ensures the given box width is valid for this component.
  818.          *
  819.          * @param     e a <code>PropertyChangeEvent</code> object describing the
  820.          *             event source and the property that has changed.
  821.          * @exception PropertyVetoException if the recipient wishes the property
  822.          *              change to be rolled back.
  823.          */
  824.         public void vetoableChange(PropertyChangeEvent e) throws PropertyVetoException
  825.         {
  826.             int i = ((Integer)e.getNewValue()).intValue();
  827.             if (!isValidBoxWidth(i))
  828.             {
  829.                 throw new PropertyVetoException("Invalid box width: " + i, e);
  830.             }
  831.         }
  832.     }
  833.  
  834.     /**
  835.      * This is the PropertyChangeEvent handling inner class for the constrained GapWidth property.
  836.      * Handles vetoing BevelHeights that are not valid.
  837.      */
  838.     class GapVeto implements java.beans.VetoableChangeListener, java.io.Serializable
  839.     {
  840.         /**
  841.          * This method gets called when an attempt to change the constrained GapWidth property is made.
  842.          * Ensures the given gap width is valid for this component.
  843.          *
  844.          * @param     e a <code>PropertyChangeEvent</code> object describing the
  845.          *             event source and the property that has changed.
  846.          * @exception PropertyVetoException if the recipient wishes the property
  847.          *              change to be rolled back.
  848.          */
  849.         public void vetoableChange(PropertyChangeEvent e) throws PropertyVetoException
  850.         {
  851.             int i = ((Integer)e.getNewValue()).intValue();
  852.             if (!isValidGapWidth(i))
  853.             {
  854.                 throw new PropertyVetoException("Invalid gap width: " + i, e);
  855.             }
  856.         }
  857.     }
  858.  
  859.     /**
  860.      * Is the given box width valid for this component.
  861.      * @param i the given box width
  862.      * @return true if the given box width is acceptable, false if not.
  863.      */
  864.     protected boolean isValidBoxWidth(int i)
  865.     {
  866.         return (i > 0);
  867.     }
  868.  
  869.     /**
  870.      * Is the given gap width valid for this component.
  871.      * @param i the given gap width
  872.      * @return true if the given gap width is acceptable, false if not.
  873.      */
  874.     protected boolean isValidGapWidth(int i)
  875.     {
  876.         return (i >= 0);
  877.     }
  878.  
  879.     /**
  880.      * Maintains the bufferImage size and draws the
  881.      * button in the bufferImage offscreen image.
  882.      * @see #paint
  883.      */
  884.     protected void updateBufferImage()
  885.     {
  886.         Dimension s        = getSize();
  887.         int width        = s.width - 1;
  888.         int height        = s.height - 1;
  889.         int barHeight    = height - indent - indent - 1;
  890.         int barOffset    = indent + 1;
  891.         Color color1    = null, color2 = null;
  892.  
  893.         if(isBufferImageInvalid())
  894.         {
  895.             bufferImage = createImage(s.width, s.height);
  896.             try
  897.             {
  898.                 MediaTracker tracker = new MediaTracker(this);
  899.                 tracker.addImage(bufferImage, 0);
  900.                 tracker.waitForID(0);
  901.             }
  902.             catch(InterruptedException e){}
  903.         }
  904.  
  905.         Graphics g = bufferImage.getGraphics();
  906.         if ( g.getClip() == null )
  907.             g.clipRect(0, 0, s.width, s.height);
  908.         Color oldColor = g.getColor();
  909.  
  910.         //Erase before we draw
  911.         g.setColor(cachedBackground);
  912.         g.fillRect(0, 0, s.width, s.height);
  913.  
  914.         //progress area and shading
  915.         g.setColor(progressColor);
  916.         int position = ((s.width - indent - indent - 2) * progress) / 100;
  917.         g.fillRect(barOffset, barOffset, position, barHeight);
  918.  
  919.         if (bDrawBoxes)
  920.         {
  921.             int totalWidth        = boxWidth + gapWidth;
  922.             int offsetConstant    = boxWidth + barOffset;
  923.             int offset            = offsetConstant;
  924.             int i                = 0;
  925.             int internalPos        = position + barOffset;
  926.  
  927.             g.setColor(cachedBackground);
  928.             while (offset <= internalPos)
  929.             {
  930.                 g.fillRect(offset, barOffset, gapWidth, barHeight);
  931.                 offset = (totalWidth * ++i) + offsetConstant;
  932.             }
  933.  
  934.             //Erase partial boxes
  935.             int xpos = (totalWidth * (i -1)) + offsetConstant + gapWidth;
  936.             int rWidth = internalPos - xpos;
  937.             if(rWidth < boxWidth)
  938.                 g.fillRect(xpos, barOffset, rWidth, barHeight);
  939.         }
  940.  
  941.         if(type != BEVEL_NONE)
  942.         {
  943.             switch(type)
  944.             {
  945.                 case BEVEL_LINE:
  946.                     color1 = color2 = borderColor;
  947.                     break;
  948.                 case BEVEL_RAISED:
  949.                     color1 = bevelLighterColor;
  950.                     color2 = bevelDarkerColor;
  951.                     break;
  952.                 case BEVEL_LOWERED:
  953.                     color1 = bevelDarkerColor;
  954.                     color2 = bevelLighterColor;
  955.                     break;
  956.             }
  957.  
  958.             // top
  959.             g.setColor(color1);
  960.             g.drawLine(indent, indent, width - indent, indent);
  961.  
  962.             // bottom
  963.             g.setColor(color2);
  964.             g.drawLine(indent, height - indent, width - indent, height - indent);
  965.  
  966.             // left
  967.             g.setColor(color1);
  968.             g.drawLine(indent, indent, indent, height - indent);
  969.  
  970.             // right
  971.             g.setColor(color2);
  972.             g.drawLine(width - indent, indent, width - indent, height - indent);
  973.         }
  974.  
  975.         // text
  976.         if (bShowProgress)
  977.         {
  978.             g.setColor(getForeground());
  979.  
  980.             FontMetrics fm = getFontMetrics(getFont());
  981.             String sz = (Integer.toString(progress) + "%");
  982.             int yTemp = ((s.height + fm.getAscent()) / 2) - 2;
  983.             int xTemp;
  984.  
  985.             switch (align)
  986.             {
  987.                 case ALIGN_LEFT:
  988.                     if (type == BEVEL_NONE)
  989.                         g.drawString(sz, 4, yTemp);
  990.                     else
  991.                         g.drawString(sz, 8, yTemp);
  992.                     break;
  993.  
  994.                 case ALIGN_RIGHT:
  995.                     xTemp = s.width - fm.stringWidth(sz);
  996.                     if (type == BEVEL_NONE)
  997.                         g.drawString(sz, xTemp - 6, yTemp);
  998.                     else
  999.                         g.drawString(sz, xTemp - 10, yTemp);
  1000.                     break;
  1001.  
  1002.                 case ALIGN_CENTERED:
  1003.                     xTemp = (s.width - fm.stringWidth(sz)) / 2;
  1004.                     if (type == BEVEL_NONE)
  1005.                         g.drawString(sz, xTemp, yTemp);
  1006.                     else
  1007.                         g.drawString(sz, xTemp, yTemp);
  1008.                     break;
  1009.             }
  1010.         }
  1011.  
  1012.         //Restore the original color
  1013.         g.setColor(oldColor);
  1014.     }
  1015.  
  1016.     /**
  1017.      * Returns true if a buffer image has been set, but it is not the
  1018.      * size of this component.
  1019.      */
  1020.     protected boolean isBufferImageInvalid()
  1021.     {
  1022.         Dimension s = getSize();
  1023.         return (bufferImage == null || s.width     != bufferImage.getWidth(this) || s.height != bufferImage.getHeight(this));
  1024.     }
  1025.  
  1026.     /**
  1027.      * Used to calculate the hilight colors from the background color.
  1028.      * @see #paint
  1029.      */
  1030.     protected void calculateHilightColors(Color c)
  1031.     {
  1032.         bevelLighterColor    = ColorUtils.calculateHilightColor(c);
  1033.         bevelDarkerColor    = ColorUtils.calculateShadowColor(c);
  1034.     }
  1035.  
  1036.     /**
  1037.      * Set the border indent amount and optionally repaint.
  1038.      * @param indent INDENT_ZERO, INDENT_ONE or INDENT_TWO
  1039.      * @param bRepaint if true, causes a repaint to occur.
  1040.      * @exception PropertyVetoException
  1041.      * if the specified property value is unacceptable
  1042.      * @see #getBorderIndent
  1043.      * @see #setBorderIndent(int)
  1044.      */
  1045.     protected void setBorderIndent(int indent, boolean bRepaint) throws PropertyVetoException
  1046.     {
  1047.         if(this.indent != indent)
  1048.         {
  1049.             Integer oldValue = new Integer(this.indent);
  1050.             Integer newValue = new Integer(indent);
  1051.  
  1052.             vetos.fireVetoableChange("borderIndent", oldValue, newValue);
  1053.  
  1054.             if (indent < INDENT_ZERO)
  1055.             {
  1056.                 this.indent = INDENT_ZERO;
  1057.             }
  1058.             else if (indent > INDENT_TWO)
  1059.             {
  1060.                 this.indent = INDENT_TWO;
  1061.             }
  1062.             else
  1063.             {
  1064.                 this.indent = indent;
  1065.             }
  1066.  
  1067.             if (bRepaint)
  1068.                 repaint();
  1069.  
  1070.             changes.firePropertyChange("borderIndent", oldValue, new Integer(this.indent));
  1071.         }
  1072.     }
  1073.  
  1074.     /**
  1075.      *    The offscreen buffer to draw the button in.
  1076.      */
  1077.     transient protected Image    bufferImage = null;
  1078.  
  1079.     /**
  1080.      * The color to use as a hilight when BevelStyle is BEVEL_RAISED or BEVEL_LOWERED.
  1081.      */
  1082.     protected Color bevelLighterColor;
  1083.     /**
  1084.      * The color to use as a hilight when BevelStyle is BEVEL_RAISED or BEVEL_LOWERED.
  1085.      */
  1086.     protected Color bevelDarkerColor;
  1087.     /**
  1088.      * Cached value of the background color.  Used to determine if calculated colors need to be updated.
  1089.      */
  1090.     protected Color cachedBackground    = null;
  1091.  
  1092.     /**
  1093.      * The value of the Border Color property.
  1094.      */
  1095.     protected Color borderColor    = null;
  1096.     /**
  1097.      * The value of the Progress Bar Color property.
  1098.      */
  1099.     protected Color progressColor    = null;
  1100.     /**
  1101.      * The value of the Show Progress property.
  1102.      */
  1103.     protected boolean bShowProgress;
  1104.     /**
  1105.      * The value of the Draw Boxes property.
  1106.      */
  1107.     protected boolean bDrawBoxes;
  1108.     /**
  1109.      * The value of the Progress Percent property.
  1110.      */
  1111.     protected int progress;
  1112.     /**
  1113.      * The value of the Box Width property.
  1114.      */
  1115.     protected int boxWidth;
  1116.     /**
  1117.      * The value of the Gap Width property.
  1118.      */
  1119.     protected int gapWidth;
  1120.     /**
  1121.      * The value of the Border Indent property.
  1122.      */
  1123.     protected int indent;
  1124.     /**
  1125.      * The value of the Alignment Style property.
  1126.      */
  1127.     protected int align;
  1128.     /**
  1129.      * The value of the Bevel Style property.
  1130.      */
  1131.     protected int type;
  1132.  
  1133.     // Private members
  1134.     private BoxVeto    boxVeto    = null;
  1135.     private GapVeto    gapVeto    = null;
  1136.     private symantec.itools.beans.VetoableChangeSupport vetos = new symantec.itools.beans.VetoableChangeSupport(this);
  1137.     private symantec.itools.beans.PropertyChangeSupport changes = new symantec.itools.beans.PropertyChangeSupport(this);
  1138. }
  1139.